<?php

namespace yunj\library\throttle;

/**
 * 滑动窗口限流
 * Class ThrottleSlider
 * @package yunj\library\throttle
 */
class SlidingWindowThrottle extends Throttle {

    /**
     * 注意：没有特别严谨，并发上来后可能会超出
     * @return bool
     */
    public function check(): bool {
        $limit = $this->getLimit();
        $duration = $this->getDuration();
        $key = $this->getKey();
        $redis = $this->getRedis();
        $now = time();

        $history = $redis->get($key);
        if ($history) {
            $history = json_decode($history, true);
            // 过滤掉失效记录
            $history = array_values(array_filter($history, function ($val) use ($now, $duration) {
                return $val >= $now - $duration;
            }));
        } else {
            $history = [];
        }
        $hasNumber = count($history);
        if ($hasNumber >= $limit) {
            // 不允许访问
            // 等待时间
            $this->waitSeconds = $duration - ($now - min($history)) + 1;
            return false;
        }
        // 允许访问
        $history[] = $now;
        $redis->setex($key, $duration, json_encode($history));
        return true;
    }

}